import warnings
warnings.warn("qturboframe.public_ui.ufc_wpf.table模块已被废弃，替代模块为qturboframe.public_ui.ucf_wpf.table", DeprecationWarning)

import time

from qturboframe.lib.utils.by import By
from qturboframe.lib.ranorex.win_control.checkbox import CheckBox as WinCheckBox
from qturboframe.lib.ranorex.exceptions import CsClientError
from qturboframe.lib.report.log import logger
from qturboframe.public_ui.ufc_wpf.basecontrol import BaseControl


class Table(BaseControl):
    """
    wpf ucf table表格对象

    :Attributes:
     - _driver: 控件所在的当前webdriver对象
     - _element: 控件元素webelement对象
     - timeout: 步骤操作的超时时间
     - table: 当前的table

    :Raises:
        当element_para类型错误时则抛出AttributeError异常

    :Example:
     - 例1: Table(webelement)
     - 例2: Table({By.TEXT:'文本信息'})
     - 例2: Table({By.CLASS_NAME:'class_name','text':'文本信息'})
     - 例3: Table({By.CLASS_NAME:'class_name','text':'文本信息'}, father=driver)
     - 例4: Table({By.CLASS_NAME:'class_name','text':'文本信息'}, father=webelement)
    """

    def __init__(self, element_para, father=None, timeout=5, index=1):
        super().__init__(element_para, father, timeout=timeout)
        self.table = self._control

    def get_table_row_no(self, header_content: dict, is_all=False):
        '''
        根据列名和列中内容获取到符合要求的表格中的数据行数

        :Args:
         - header_content: 字典类型，为table的某一header名和某一行的内容组成的字典例如：{"证券代码":"600570","委托序号":"54691,54693"}
           当有一个内容需要查找多个时则用逗号(,)分隔
         - is_all: 是否获取到符合要求的所有的行（是否进行分页查找），目前才参数无效

        :Returns:
            返回符合内容的行数 - list类型

        :Raises:
            None

        :Example:
         - 例: table.get_table_row_no({"证券代码":"600570","委托序号":"54691,54693"})
        '''
        table_title_list = self.__get_table_titles()  # 得到table的header

        query_dic = {}
        for key, value in header_content.items():
            #得到表格头部和对应列要找到内容的字典
            #例如表格头部为['', '委托序号', '委托批号', '申报编号', '证券代码', '证券名称', '委托方向', '委托数量', '委托价格', '价格类型', '委托状态', '挂单数量', '成交均价', '投资类型', '手/自', '委托时间', '基金', '组合', '投资组合ID', '投资组合名称', '方案批号', '指令序号', '操作员', '操作员名称']
            #header_content为{"证券代码":"600570","委托序号":"54691,54693"}
            #则query_dic为{"5":"600570","2":"54691,54693"}
            query_dic[table_title_list.index(key) + 1] = value #key为table的列，value为要查找的列的内容

        column_index_value_position_dic = {}
        for key,  value in query_dic.items():
            td_xpath = ".//row//list//cell[{}]".format(key)
            tds = self.table.find_elements_by_attribute(By.XPATH, td_xpath, timeout=0.2)
            #获取到对应列的内容
            content_list = self.__get_cell_texts(tds)

            #从对应列中获取到对应符合要求的行
            value_list = value.split(',')
            position = []
            for temp in value_list:
                # position_temp = [pos for pos, value in enumerate(content_list) if value==temp]
                position_temp = self.__get_value_index(content_list, temp)
                position.extend(position_temp)
            column_index_value_position_dic[key] = position

        #获取字典中对应value的合集
        position_value_list = []
        for key, value in column_index_value_position_dic.items():
            position_value_list.append(value)

        if len(position_value_list)>1:
            result_set = set(position_value_list[0])
            for temp_set in position_value_list[1:]:
                result_set = result_set.intersection(temp_set)
            # 返回符合要求的行数
            # is_all为True时，进行翻页查找获取所有行，is_all为False,只获取到第一页符合要求的所有行
            return list(result_set)
        else:
            return position_value_list[0]

    def get_table_rows(self, header_content: dict, is_all=False):
        '''
        根据列名和列名信息查找在表格中所在的行数,字典key为table为列名，字典值为table为内容，

        :Args:
         - header_content: 字典类型，为table的某一header名和某一行的内容组成的字典例如：{"委托序号":"54691","证券代码":"600570"}
         - is_all: 是否获取到符合要求的所有的行(判断是否进行翻页-目前此参数无效)

        :Returns:
            返回查找的某一行所有元素,类型为List<WebElement>

        :Raises:
            CsClientError: 表格行数查找失败

        :Example:
         - 例: table.get_table_rows({"证券代码":"600570","委托序号":"54691,54693"})
        '''
        row_no_ret = self.get_table_row_no(header_content, is_all)
        if len(row_no_ret)>0:
            row_list = []
            for row_no in row_no_ret:
                xpath = ".//row[{}]".format(row_no)
                row = self.table.find_element_by_attribute(By.XPATH, xpath, timeout=1000)
                row_list.append(row)
            return row_list
        else:
            raise CsClientError("没有找到符合此{}要求的数据行".format(header_content))

    def select_row_in_table(self, header_content: dict=None, is_all=False, is_selected_all=False):
        '''
        根据列名和列名信息,选中表格中的行

        :Args:
         - header_content: 字典类型，为table的某一header名和某一行的内容组成的字典例如：{"委托序号":"54691","证券代码":"600570"}
         - is_all: 是否获取到符合要求的所有的行(判断是否进行翻页-目前此参数无效)
         - is_selected_all: 是否全选

        :Returns:
            返回查找的某一行所有元素,类型为List<WebElement>

        :Raises:
            CsClientError: 表格行数查找失败

        :Example:
         - 例: table.select_row_in_table({"证券代码":"600570","委托序号":"54691,54693"})
        '''
        #取消所有已选中的复选框
        #获取table头部的checkbox
        #如果头部有checkbox则选择行时，勾选checkbox进行选择，否则直接点击某一行进行选择
        xpath = ".//list[@automationid='PART_ColumnHeadersPresenter']//cell//checkbox"
        header_checkbox = self.table.exist(By.XPATH, xpath, timeout=1000)
        if header_checkbox:
            header_checkbox_control = WinCheckBox(header_checkbox.control)
            if header_checkbox_control.get_check_state():
                header_checkbox.click()
            else:
                #用header_checkxbox.click可以使所有列被选中，header_checkbox_control.check()只能使头部的checkbox被选中
                header_checkbox.click()#先全部选中
                header_checkbox.click()#再取消选中

        #全选中
        #只有表格中有checkbox时有效
        if is_selected_all and header_checkbox:
            if not header_checkbox_control.get_check_state():
                header_checkbox.click()
                return

        #当is_selected_all全选中时，则不用再执行下面操作
        row_controls = self.get_table_rows(header_content)
        if header_checkbox:
            for row in row_controls:
                checkbox = row.find_element_by_attribute(By.XPATH, ".//checkbox", timeout=1000)
                win_check_box = WinCheckBox(checkbox.control)
                if not win_check_box.get_check_state():
                    win_check_box.check()
        else:
            # 只操作获取到的第一行
            row = row_controls[0]
            row.click()

    def click_cell_in_table(self, heade_content: dict=None, is_all=False, is_modify_all=False):
        '''
        根据列名和列名信息获取cell,点击cell中的按钮

        :Args:
         - header_content: 字典类型，为table的某一header名和某一行的内容组成的字典例如：{"委托序号":"54691","证券代码":"600570","监控公式":"C+K-P#I"}
           带有#I标识的数据标识要输入的数据
         - is_all: 是否获取到符合要求的所有的行(判断是否进行翻页-目前此参数无效)
         - is_modify_all: 是否全部修改

        :Returns:
            None

        :Raises:
            CsClientError: 表格行数查找失败

        :Example:
         - 例: table.click_cell_in_table({"认购期权":"上汽集团购3月1100,中国平安购3月4250","监控公式":"C+K-P#I"})
        '''
        query_header_content={}
        open_content=''
        for key, value in heade_content.items():
            if value=="":
                #value为空，表示要点击此单元格
                open_content = value
            else:
                #获取到要查询的列头和内容信息
                query_header_content[key] = value

        row_controls = []
        if is_modify_all:
            #获取所有的行数
            row_controls = self.table.find_elements_by_attribute(By.XPATH,".//list", timeout=self.timeout)
            row_controls = row_controls[1:]
        else:
            row_controls = self.get_table_rows(query_header_content)

        #只操作获取到的第一行
        row = row_controls[0]
        title_list = self.__get_table_titles()
        # logger.debug("表头:{}".format(title_list))
        index = title_list.index(key) + 1  # 要点击列的索引
        #点击button按钮
        button_xpath = ".//cell[{}]//button".format(index)
        checkbox_xpath = ".//cell[{}]//checkbox".format(index)
        button_control = row.exist(By.XPATH, button_xpath, timeout=0.1)
        if button_control:
            button_control.click()
            return
        checkbox_control = row.exist(By.XPATH, checkbox_xpath, timeout=0.1)
        if checkbox_control:
            WinCheckBox(checkbox_control.control).click()
            return

        raise CsClientError("点击table中的按钮，但是在'{}'列下没有找到可点击的按钮".format(open_content))

    def __get_cell_texts(self, cells):
        text_list = []
        for cell in cells:
            text = cell.get_attribute_value("Text")
            if text:
                #如果cell的Text有值，则直接获取cell的Text值
                text_list.append(text.strip())
            else:
                #否则判断cell是否有text子元素，有的话则获取text的值，否则文本值为空
                temp = cell.exist(By.XPATH, ".//text[@Type='TextBlock']", timeout=0.1)
                if temp:
                    text_list.append(temp.get_text())
                else:
                    text_list.append("")

        return text_list

    def __get_table_titles(self):
        """
        获取table的header
        """
        xpath = ".//list[@automationid='PART_ColumnHeadersPresenter']//cell"
        header_cells = self.table.find_elements_by_attribute(By.XPATH, xpath, timeout=self.timeout)
        return self.__get_cell_texts(header_cells)

    def __get_value_index(self, content_list, expected_value):
        pos_list = []
        for pos, value in enumerate(content_list):
            if expected_value in value:
                pos_list.append(pos+1)

        return pos_list







